<!DOCTYPE html>
<head>
	<meta http-equiv="Content-type" content="text/html; charset=utf-8">
	<title>Group by multiple resources</title>
	<script src="../../codebase/dhtmlxgantt.js?v=7.1.7"></script>
	<script src="./common/jquery_multiselect.js?v=7.1.7"></script>
	<link rel="stylesheet" href="./common/jquery_multiselect.css?v=7.1.7">
	<link rel="stylesheet" href="../common/controls_styles.css?v=7.1.7">
	<script
			src="https://code.jquery.com/jquery-3.3.1.min.js?v=7.1.7"
			integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
			crossorigin="anonymous"></script>

	<script src="https://cdnjs.cloudflare.com/ajax/libs/chosen/1.8.7/chosen.jquery.js?v=7.1.7"></script>

	<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/chosen/1.8.7/chosen.css?v=7.1.7">

	<link rel="stylesheet" href="../../codebase/dhtmlxgantt.css?v=7.1.7">

	<script src="../common/resource_project_construction.js?v=7.1.7"></script>
	<style>
		html, body {
			padding: 0px;
			margin: 0px;
			height: 100%;
		}

		#gantt_here {
			width:100%;
			height: 800px;
			height:calc(100vh - 52px);
		}

		.gantt_grid_scale .gantt_grid_head_cell,
		.gantt_task .gantt_task_scale .gantt_scale_cell {
			font-weight: bold;
			font-size: 14px;
			color: rgba(0, 0, 0, 0.7);
		}

		.resource_marker{
			text-align: center;
		}
		.resource_marker div{
			width: 28px;
			height: 28px;
			line-height: 29px;
			display: inline-block;

			color: #FFF;
			margin: 3px;
		}
		.resource_marker.workday_ok div {
			border-radius: 15px;
			background: #51c185;
		}

		.resource_marker.workday_over div{
			border-radius: 3px;
			background: #ff8686;
		}

		.folder_row {
			font-weight: bold;
		}

		.highlighted_resource,
		.highlighted_resource.odd
		{
			background-color: rgba(255, 251, 224, 0.6);
		}
	
		.resource-controls .gantt_layout_content{
			padding: 7px;
			overflow: hidden;
		}
		.resource-controls label{
			margin: 0 10px;
			vertical-align: bottom;
			display: inline-block;
			color: #3e3e3e;
			padding: 2px;
			transition: box-shadow 0.2s;
		}

		.resource-controls label:hover{
			box-shadow: 0 2px rgba(84, 147, 255, 0.42);
		}

		.resource-controls label.active,
		.resource-controls label.active:hover
		{
			box-shadow: 0 2px #5493ffae;
			color: #1f1f1f;
		}

		.resource-controls input{
			vertical-align: top;
		}

		.gantt_task_cell.week_end {
			background-color: #e8e8e87d;
		}

		.gantt_task_row.gantt_selected .gantt_task_cell.week_end {
			background-color: #e8e8e87d !important;
		}


		.group_row,
		.group_row.odd,
		.gantt_task_row.group_row{
			background-color: rgba(232, 232, 232, 0.6);
		}

		.owner-label{
			width: 20px;
			height: 20px;
			line-height: 20px;
			font-size: 12px;
			display: inline-block;
			border: 1px solid #cccccc;
			border-radius: 25px;
			background: #e6e6e6;
			color: #6f6f6f;
			margin: 0 3px;
			font-weight: bold;
		}

	</style>
</head>
<body>
<div class="gantt_control" >
	<input type='button' id='default' onclick="toggleGroups(this)" value="Show Resource view">
</div>

<div id="gantt_here"></div>
<script>
	gantt.plugins({
		grouping: true,
		auto_scheduling: true
	});

	gantt.config.date_format = "%Y-%m-%d %H:%i:%s";

	function shouldHighlightTask(task){
		var store = gantt.$resourcesStore;
		var taskResource = task[gantt.config.resource_property],
			selectedResource = store.getSelectedId();
		if(taskResource == selectedResource || store.isChildOf(taskResource, selectedResource)){
			return true;
		}
	}

	gantt.templates.grid_row_class = function(start, end, task){
		var css = [];
		if(gantt.hasChild(task.id)){
			css.push("folder_row");
		}

		if(task.$virtual){
			css.push("group_row")
		}

		if(shouldHighlightTask(task)){
			css.push("highlighted_resource");
		}

		return css.join(" ");
	};

	gantt.templates.task_row_class = function(start, end, task){
		if(shouldHighlightTask(task)){
			return "highlighted_resource";
		}
		return "";
	};

	gantt.templates.timeline_cell_class = function (task, date) {
		if (!gantt.isWorkTime({date: date, task: task}))
			return "week_end";
		return "";
	};

	gantt.templates.resource_cell_class = function(start_date, end_date, resource, tasks){
		var css = [];
		css.push("resource_marker");
		if (tasks.length <= 1) {
			css.push("workday_ok");
		} else {
			css.push("workday_over");
		}
		return css.join(" ");
	};

	gantt.templates.resource_cell_value = function(start_date, end_date, resource, tasks){
		var html = "<div>"
		if(resourceMode == "hours"){
			html += tasks.length * 8;
		}else{
			html += tasks.length;
		}
		html += "</div>";
		return html;
	};

	function shouldHighlightResource(resource){
		var selectedTaskId = gantt.getState().selected_task;
		if(gantt.isTaskExists(selectedTaskId)){
			var selectedTask = gantt.getTask(selectedTaskId),
				selectedResource = selectedTask[gantt.config.resource_property];

			if(resource.id == selectedResource){
				return true;
			}else if(gantt.$resourcesStore.isChildOf(selectedResource, resource.id)){
				return true;
			}
		}
		return false;
	}

	var resourceTemplates = {
		grid_row_class: function(start, end, resource){
			var css = [];
			if(gantt.$resourcesStore.hasChild(resource.id)){
				css.push("folder_row");
				css.push("group_row");
			}
			if(shouldHighlightResource(resource)){
				css.push("highlighted_resource");
			}
			return css.join(" ");
		},
		task_row_class: function(start, end, resource){
			var css = [];
			if(shouldHighlightResource(resource)){
				css.push("highlighted_resource");
			}
			if(gantt.$resourcesStore.hasChild(resource.id)){
				css.push("group_row");
			}

			return css.join(" ");

		}
	};

	gantt.locale.labels.section_owner = "Owner";
	gantt.config.lightbox.sections = [
		{name: "description", height: 38, map_to: "text", type: "textarea", focus: true},
		{name: "owner",height: 60, type:"multiselect", options: gantt.serverList("people"), map_to:"owner_id", unassigned_value:5 },
		{name: "time", type: "duration", map_to: "auto"}
	];

	function getResourceTasks(resourceId) {
		var store = gantt.getDatastore(gantt.config.resource_store),
			field = gantt.config.resource_property,
			tasks;

		if (store.hasChild(resourceId)) {
			tasks = gantt.getTaskBy(field, store.getChildren(resourceId));
		}else{
			tasks = gantt.getTaskBy(field, resourceId);
		}
		return tasks;
	}

	var resourceConfig = {
		scale_height: 30,
		scales: [
			{unit: "day", step: 1, date: "%d %M"}
		],
		columns: [
			{
				name: "name", label: "Name", tree:true, width:250, template: function (resource) {
					return resource.text;
				}, resize: true
			},
			{
				name: "specialty", label: "Speciality", width:150, align:"center",template: function (resource) {

					return resource.specialty || "";
				}, resize: true
			},
			{
				name: "workload", label: "Workload", align:"center", template: function (resource) {
					var tasks = getResourceTasks(resource.id);
					var totalDuration = 0;
					tasks.forEach(function(task){
						totalDuration += task.duration;
					});

					return (totalDuration || 0) * 8 + "h";
				}, resize: true
			},

			{
				name: "capacity", label: "Capacity", align:"center",template: function (resource) {
					var store = gantt.getDatastore(gantt.config.resource_store);
					var n = store.hasChild(resource.id) ? store.getChildren(resource.id).length : 1

					var state = gantt.getState();

					return gantt.calculateDuration(state.min_date, state.max_date) * n * 8 + "h";
				}
			}

		]
	};

	gantt.config.scales = [
		{unit: "month", step: 1, format: "%F, %Y"},
		{unit: "day", step: 1, format: "%d %M"}
	];

	gantt.config.auto_scheduling = true;
	gantt.config.auto_scheduling_strict = true;
	gantt.config.work_time = true;
	gantt.config.columns = [
		{name: "text", tree: true, width: 320, resize: true},
		{name: "start_date", align: "center", width: 80, resize: true},
		{name: "owner", align: "center", width: 80, label: "Owner", resize: true,
			template: function (task) {
				if (task.type == gantt.config.types.project) {
					return "";
				}

				var result = "";
				var store = gantt.getDatastore("resource");
				var owners = task[gantt.config.resource_property];

				if (!owners || !owners.length) {
					return "Unassigned";
				}

				if(owners.length == 1){
					return store.getItem(owners[0]).text;
				}

				owners.forEach(function(ownerId) {
					var owner = store.getItem(ownerId);
					if (!owner)
						return;
					result += "<div class='owner-label' title='" + owner.text + "'>" + owner.text.substr(0, 1) + "</div>";

				});

				return result;
			}
		},
		{name: "duration", width: 60, align: "center", resize: true},
		{name: "add", width: 44}
	];

	gantt.config.resource_store = "resource";
	gantt.config.resource_property = "owner_id";
	gantt.config.order_branch = true;
	gantt.config.open_tree_initially = true;
	gantt.config.scale_height = 50;
	gantt.config.layout = {
		css: "gantt_container",
		rows: [
			{
				gravity: 2,
				cols: [
					{view: "grid", group:"grids", scrollY: "scrollVer"},
					{resizer: true, width: 1},
					{view: "timeline", scrollX: "scrollHor", scrollY: "scrollVer"},
					{view: "scrollbar", id: "scrollVer", group:"vertical"}
				]
			},
			{ resizer: true, width: 1, next: "resources"},
			{
				height: 35,
				cols: [
					{ html:"", group:"grids"},
					{ resizer: true, width: 1},
					{ html:"<label class='active' >Hours per day <input checked type='radio' name='resource-mode' value='hours'></label>" +
					"<label>Tasks per day <input type='radio' name='resource-mode' value='tasks'></label>", css:"resource-controls"}
				]
			},

			{
				gravity:1,
				id: "resources",
				config: resourceConfig,
				templates: resourceTemplates,
				cols: [
					{ view: "resourceGrid", group:"grids", scrollY: "resourceVScroll" },
					{ resizer: true, width: 1},
					{ view: "resourceTimeline", scrollX: "scrollHor", scrollY: "resourceVScroll"},
					{ view: "scrollbar", id: "resourceVScroll", group:"vertical"}
				]
			},
			{view: "scrollbar", id: "scrollHor"}
		]
	};

	var resourceMode = "hours";
	gantt.attachEvent("onGanttReady", function() {
		var radios = [].slice.call(gantt.$container.querySelectorAll("[name='resource-mode']"));
		radios.forEach(function(radio) {
			gantt.event(radio, "change", function(e) {
				radios.forEach(function(item) {
					item.parentNode.classList.toggle("active", e.target === item || e.target.value === item.value);
				});
				if (this.checked) {
					resourceMode = this.value;
					gantt.getDatastore(gantt.config.resource_store).refresh();
				}
			});
		});
	});

	gantt.$resourcesStore = gantt.createDatastore({
		name: gantt.config.resource_store,
		type: "treeDatastore",
		initItem: function (item) {
			item.parent = item.parent || gantt.config.root_id;
			item[gantt.config.resource_property] = item.parent;
			item.open = true;
			return item;
		}
	});

	gantt.$resourcesStore.attachEvent("onAfterSelect", function(id){
		gantt.refreshData();
	});

	gantt.init("gantt_here");


	function toggleGroups(input) {
		gantt.$groupMode = !gantt.$groupMode;
		if (gantt.$groupMode) {
			input.value = "show gantt view";

			var groups = gantt.$resourcesStore.getItems().map(function(item){
				var group = gantt.copy(item);
				group.group_id = group.id;
				group.id = gantt.uid();
				return group;
			});

			gantt.groupBy({
				groups: groups,
				relation_property: gantt.config.resource_property,
				group_id: "group_id",
				group_text: "text",
				delimiter: ", ",
				default_group_label: "Not Assigned"
			});
		} else {
			input.value = "show resource view";
			gantt.groupBy(false);
		}
	}

	gantt.$resourcesStore.attachEvent("onParse", function(){
		var people = [];
		gantt.$resourcesStore.eachItem(function(res){
			if(!gantt.$resourcesStore.hasChild(res.id)){
				var copy = gantt.copy(res);
				copy.key = res.id;
				copy.label = res.text;
				if(copy.specialty){
					copy.label += ", " + copy.specialty;
				}
				people.push(copy);
			}
		});
		gantt.updateCollection("people", people);
	});

	gantt.$resourcesStore.parse([
		{id:1, text:"Architect"},
		{id:2, text:"Construction worker"},
		{id:3, text:"Plasterer"},
		{id:4, text:"Plumber"},
		{id:5, text:"Electrician"},
		{id:6, text:"Handyman"},
		{id: 7, text: "Anna", specialty: "Architect", parent:1},
		{id: 8, text: "Finn", specialty: "Construction worker", parent:2},
		{id: 9, text: "Jake", specialty: "Construction worker", parent:2},
		{id: 10, text: "Floe", specialty: "Plasterer", parent:3},
		{id: 11, text: "Tom", specialty: "Plumber", parent:4},
		{id: 12, text: "Mike", specialty: "Electrician", parent:5},
		{id: 13, text: "Joe", specialty: "Handyman", parent:6}
	]);

	gantt.parse(taskData);
</script>
</body>